package com.chu.cloud.api.controller;

import com.chu.cloud.api.base.BaseController;
import com.chu.cloud.api.service.SeckillOrderFuture;
import com.chu.cloud.api.thread.MemberContextLocal;
import com.chu.cloud.dto.order.CommonOrderCreateDto;
import com.chu.cloud.dto.order.OrderResult;
import com.chu.cloud.dto.order.SeckillResult;
import com.chu.cloud.enums.OrderType;
import com.chu.cloud.enums.RedisKeyPrefix;
import com.chu.cloud.feign.client.IOrderFeignClient;
import com.chu.cloud.response.ResponseMessage;
import com.chu.cloud.response.ResultVo;
import com.chu.cloud.util.ChuException;
import com.chu.cloud.util.RedisUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.CompletableFuture;

/**
 * @author: Tianshu.CHU
 * @Date: 2018/6/8 17:08
 * @Description:
 */
@RestController
@RequestMapping("/orders")
@Slf4j
public class OrderController extends BaseController {

    @Autowired
    private IOrderFeignClient orderFeignClient;

    @Autowired
    private SeckillOrderFuture seckillOrderFuture;

    @PostMapping("/generate/common")
    public CompletableFuture<ResultVo<OrderResult>> generateCommon(@RequestBody CommonOrderCreateDto orderCreateDto, HttpServletRequest request) {
        Integer userId = MemberContextLocal.get().getId();
        orderCreateDto.setIp(getIp(request));
        orderCreateDto.setMemberId(userId);
        return CompletableFuture.supplyAsync(() -> {
            ResponseMessage<OrderResult> result = orderFeignClient.generate(orderCreateDto);
            if (result.getCode() != 200) {
                throw new ChuException(result.getMessage());
            }
            return result.getData();
        }).thenApply(ResultVo::ok);
    }

    @ApiOperation(value = "执行秒杀", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "actId", value = "活动Id"),
            @ApiImplicitParam(name = "productId", value = "商品Id"),
            @ApiImplicitParam(name = "quantity", value = "秒杀数量")
    })
    @PostMapping("/execute/seckill/{actId}/{productId}/{quantity}")
    public CompletableFuture<ResultVo<String>> generateSeckill(@PathVariable Integer actId, @PathVariable Integer productId,
                                                               @PathVariable Integer quantity, HttpServletRequest request) {
        String ip = BaseController.getIp(request);
        Integer userId = MemberContextLocal.get().getId();
        return CompletableFuture
                .supplyAsync(() -> seckillOrderFuture.prepareSeckillOrder(userId, actId, productId, quantity))
                .thenCompose(result -> {
                    result.setIp(ip);
                    result.setOrderType(OrderType.SECKILL);
                    return seckillOrderFuture.execute(result);
                })
                .thenApply(ResultVo::ok);
    }

    @GetMapping("/seckill/result/{actId}/{productId}")
    public CompletableFuture<ResultVo<SeckillResult>> result(@PathVariable Integer actId, @PathVariable Integer productId) {
        final String field = actId + ":" + productId;
        Integer userId = MemberContextLocal.get().getId();
        return CompletableFuture.supplyAsync(() ->{
            SeckillResult result = RedisUtil.hGet(RedisKeyPrefix.SECKILL_RESULT_USER, userId, field);
            if (result == null) {
                if (RedisUtil.hExist(RedisKeyPrefix.SECKILL_OPEN_FLAG, userId, field)) {
                    return ResultVo.errorOfMessage("秒杀失败");
                }
            }
            return ResultVo.ok(result);
        });
    }
}
